﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;

namespace QAToolsAddin.Components {
    public partial class DropDownCheckBox : UserControl {
        [DllImport("User32.dll", EntryPoint = "GetDCEx")]
        internal static extern IntPtr GetDCEx(IntPtr hWnd, IntPtr hRgn, int flags);

        private CheckedPopup popup;
        private Pen _focudPen;
        private Pen _borderPenEnabled;
        private Pen _borderPenDisabled;
        private Pen _borderPen;
        private bool _cancelNextOpen;
        private Image _img_dropdown;
        private Image _img_dropdown_over;
        private Image _img_dropdown_click;
        private Image _img_dropdown_disabled;

        public DropDownCheckBox() {
            _focudPen = new Pen(Color.FromArgb(127, 157, 185), 1);
            _focudPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
            _borderPenEnabled = new Pen(Color.FromArgb(127, 157, 185), 1);
            _borderPenDisabled = new Pen(Color.FromArgb(201, 199, 186), 1);
            _borderPen = _borderPenEnabled;
            InitializeComponent();
            ComponentResourceManager resources = new ComponentResourceManager(typeof(DropDownCheckBox));
            _img_dropdown = ((System.Drawing.Image)(resources.GetObject("dropdown")));
            _img_dropdown_over = ((System.Drawing.Image)(resources.GetObject("dropdown_over")));
            _img_dropdown_click = ((System.Drawing.Image)(resources.GetObject("dropdown_click")));
            _img_dropdown_disabled = ((System.Drawing.Image)(resources.GetObject("dropdown_disabled")));
            btDrop.Image = _img_dropdown;
            btDrop.InitialImage = _img_dropdown;

        }

        protected override void OnLoad(EventArgs e) {
            popup = new CheckedPopup(this.ParentForm);
            popup.Closing += OnPopupClosing;
            popup.CheckingChanged += OnPopupCheckingChanged;
            popup.Opened += OnPopupOpened;
        }

        public new bool Enabled {
            set {
                if (value) {
                    _borderPen = _borderPenEnabled;
                    btDrop.Image = _img_dropdown;
                } else {
                    _borderPen = _borderPenDisabled;
                    btDrop.Image = _img_dropdown_disabled;
                }
                base.Enabled = value;
            }
        }

        public void SetColumnSelector(Excel.Range range, bool hasHeaders) {
            if (range == null) {
                this.Items = null;
                return;
            }
            var rgTiles = (Excel.Range)range.Rows[1];
            List<DropDownCheckBox.CheckItem> titles = new List<DropDownCheckBox.CheckItem>();
            int baseCol = range.Column - 1;
            int c = 0;
            foreach (Excel.Range cell in rgTiles.Cells) {
                if (++c == 50) break;
                if ((double)cell.ColumnWidth != 0) {
                    int colIndex = cell.Column;
                    int colPos = colIndex - baseCol;
                    string colstr = Utils.GetColumnLetters(colIndex);
                    if (hasHeaders)
                        titles.Add(new DropDownCheckBox.CheckItem(colPos, colstr + "-" + (string)cell.Text, colstr, false));
                    else
                        titles.Add(new DropDownCheckBox.CheckItem(colPos, colstr, colstr, false));
                }
            }
            this.Items = titles.ToArray();
        }

        public CheckItem[] Items {
            get {
                if (popup != null)
                    return popup.CheckItems;
                return null;
            }
            set {
                if (popup != null) {
                    popup.UpdateItems(value);
                    RefreshValue();
                }
            }
        }

        public bool IsEmpty {
            get {
                foreach (CheckItem item in popup.CheckItems) {
                    if (item.Checked) return false;
                }
                return true;
            }
        }

        public int[] CheckedIds {
            get {
                List<int> index = new List<int>();
                foreach (CheckItem item in popup.CheckItems)
                    if (item.Checked) index.Add(item.Id);
                return index.ToArray();
            }
        }

        public int[] UncheckedIds {
            get {
                List<int> index = new List<int>();
                foreach (CheckItem item in popup.CheckItems)
                    if (item.Checked == false) index.Add(item.Id);
                return index.ToArray();
            }
        }

        private void OnPopupCheckingChanged(object sender, EventArgs e) {
            RefreshValue();
        }

        private void OnPopupOpened(object sender, EventArgs e) {
            this.btDrop.Image = _img_dropdown_click;
        }

        private void OnPopupClosing(object sender, ToolStripDropDownClosingEventArgs e) {
            if (e.CloseReason == ToolStripDropDownCloseReason.AppClicked) {
                Point pos = PointToClient(Control.MousePosition);
                if (pos.X > 0 && pos.Y > 0 && pos.X < this.Width && pos.Y < this.Height)
                    _cancelNextOpen = true;
            }
            this.btDrop.Image = _img_dropdown;
        }

        public void RefreshValue() {
            StringBuilder sb = new StringBuilder();
            if (popup.CheckItems != null) {
                int nbItems = popup.CheckItems.Length;
                foreach (CheckItem item in popup.CheckItems) {
                    if (item.Checked) {
                        if (sb.Length != 0) sb.Append(",");
                        sb.Append(item.ShortName);
                    }
                }
            }
            ctrlValue.Text = sb.ToString();
        }

        protected override void OnPaint(PaintEventArgs e) {
            base.OnPaint(e);
            using (Graphics grfx = Graphics.FromHdc(GetDCEx(this.Handle, IntPtr.Zero, 1027))) {
                Rectangle rectborder = new Rectangle(0, 0, this.Width - 1, this.Height - 1);
                grfx.DrawRectangle(_borderPen, rectborder);
            }
        }

        private void control_Click(object sender, EventArgs e) {
            if (_cancelNextOpen) {
                _cancelNextOpen = false;
                return;
            } else {
                popup.Show(this);
            }
        }

        private void DropDownCheckBox_KeyPress(object sender, KeyPressEventArgs e) {
            if (e.KeyChar == (char)Keys.Enter || e.KeyChar == (char)Keys.Space) {
                popup.Show(this);
                e.Handled = true;
            }
        }

        public class CheckItem {
            private string _longName;
            private string _shortName;
            private bool _checked;
            private int _id;

            public CheckItem(int id, string longName, string shortName, bool isChecked) {
                _id = id;
                _longName = longName;
                _shortName = shortName;
                _checked = isChecked;
            }

            public int Id {
                get { return _id; }
                set { _id = value; }
            }

            public string LongName {
                get { return _longName; }
                set { _longName = value; }
            }

            public string ShortName {
                get { return _shortName; }
                set { _shortName = value; }
            }

            public bool Checked {
                get { return _checked; }
                set { _checked = value; }
            }
        }

        public class CheckedPopup : ToolStripDropDown {
            private System.Windows.Forms.ToolStripControlHost _host;
            private CheckedListBox checkedListBox1;
            private CheckItem[] _items;

            public event EventHandler CheckingChanged;

            public CheckedPopup(Form owner) {
                checkedListBox1 = new CheckedListBox();
                checkedListBox1.CheckOnClick = true;
                checkedListBox1.FormattingEnabled = true;
                checkedListBox1.BorderStyle = BorderStyle.None;
                base.AutoSize = true;
                base.DropShadowEnabled = false;
                base.Padding = new Padding(2, 1, 2, 0);
                base.DoubleBuffered = true;
                base.ResizeRedraw = true;
                _host = new ToolStripControlHost(checkedListBox1);
                base.Items.Add(this._host);
                checkedListBox1.ItemCheck += OnItemCheck;

            }

            protected override DockStyle DefaultDock {
                get { return DockStyle.Left | DockStyle.Top; }
            }

            private void OnItemCheck(object sender, ItemCheckEventArgs e) {
                _items[e.Index].Checked = e.NewValue == CheckState.Checked;
                if (CheckingChanged != null)
                    CheckingChanged(this, null);
            }

            public CheckItem[] CheckItems {
                get {
                    return _items;
                }
                set {
                    _items = value;
                    checkedListBox1.SuspendLayout();
                    checkedListBox1.Items.Clear();
                    if (_items != null) {
                        foreach (var item in value)
                            checkedListBox1.Items.Add(item.LongName, item.Checked);
                    }
                    checkedListBox1.ResumeLayout();
                }
            }

            public void UpdateItems(CheckItem[] newItems) {
                if (newItems != null && this.CheckItems != null) {
                    CheckItem[] curItems = this.CheckItems;
                    foreach (CheckItem item in newItems) {
                        int nbItems = curItems.Length;
                        for (int i = 0; i < nbItems; i++) {
                            if (curItems[i].ShortName == item.ShortName) {
                                item.Checked = curItems[i].Checked;
                                break;
                            }
                        }
                    }
                }
                this.CheckItems = newItems;
            }

            public CheckedListBox CheckedListBox {
                get { return this.checkedListBox1; }
            }

            internal void Show(Control control) {
                checkedListBox1.MinimumSize = new Size(control.Width - 4, 0);
                checkedListBox1.MaximumSize = new Size(control.Width * 3, 304);
                control.Focus();
                base.Show(control, new Point(-1, control.Height - 1));
                checkedListBox1.Focus();
            }

            protected override bool ProcessDialogKey(Keys keyData) {
                if (keyData == Keys.Escape || keyData == Keys.Tab || keyData == Keys.Enter) {
                    this.Hide();
                    return true;
                }
                return false;
            }
        }

        private void btDrop_MouseHover(object sender, EventArgs e) {
            this.btDrop.Image = _img_dropdown_over;
        }

        private void btDrop_MouseLeave(object sender, EventArgs e) {
            if (popup.Visible == false)
                this.btDrop.Image = _img_dropdown;
        }

    }
}
